import { isObject } from "../utils"
import { nextTick, ref, type Ref } from "vue"

export interface NetworkState {
    since?: Date;
    online?: boolean;
    rtt?: number;
    type?: string;
    downlink?: number;
    saveData?: boolean;
    downlinkMax?: number;
    effectiveType?: string;
}
export type removeHandel = () => void
  
enum NetworkEventType {
    ONLINE = 'online',
    OFFLINE = 'offline',
    CHANGE = 'change',
}

function getConnection() {
    const nav = navigator as any;
    if (!isObject(nav)) return null;
    return nav.connection || nav.mozConnection || nav.webkitConnection;
}

function getConnectionProperty(): NetworkState {
    const c = getConnection();
    if (!c) return {};
    return {
      rtt: c.rtt,
      type: c.type,
      saveData: c.saveData,
      downlink: c.downlink,
      downlinkMax: c.downlinkMax,
      effectiveType: c.effectiveType,
    };
}

/**
 * @param {{
 *     onOnline?: (state: NetworkState) => void,
 *     onOffline?: (state: NetworkState) => void,
 *     onChangeline?: (state: NetworkState) => void
 * }} [options] 可选参数，事件回调onOnline、onOffline、onChangeline
 * @returns {Ref<NetworkState>}
 */
export function useNetwork(options?: {
    onOnline?: (state: NetworkState) => void,
    onOffline?: (state: NetworkState) => void,
    onChangeline?: (state: NetworkState) => void
}): Ref<NetworkState> {
    
    const state = ref<NetworkState>({
        since: undefined,
        online: navigator?.onLine,
        ...getConnectionProperty()
    })

    const onOnline = () => {
        state.value = {
            ...state.value,
            online: true,
            since: new Date(),
        }
        options?.onOnline && options?.onOnline(state.value)
    }
    const onOffline = () => {
        state.value = {
            ...state.value,
            online: false,
            since: new Date(),
        }
        options?.onOffline && options?.onOffline(state.value)
    }
    const onConnectionChange = () => {
        state.value = {
            ...state.value,
            ...getConnectionProperty()
        }
        options?.onChangeline && options?.onChangeline(state.value)
    }

    window.addEventListener(NetworkEventType.ONLINE, onOnline);
    window.addEventListener(NetworkEventType.OFFLINE, onOffline);

    const connection = getConnection();
    connection?.addEventListener(NetworkEventType.CHANGE, onConnectionChange);

    const remove = () => {
        window.removeEventListener(NetworkEventType.ONLINE, onOnline);
        window.removeEventListener(NetworkEventType.OFFLINE, onOffline);
        connection?.removeEventListener(NetworkEventType.CHANGE, onConnectionChange);
    }

    // return [ state,  remove ]

    return state
}